home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mntlib43
/
mntlib
/
lattice
/
_divmods.s
next >
Wrap
Text File
|
1992-06-15
|
2KB
|
84 lines
; long division and modulus routines
;
; written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
;
;
; Revision 1.1, kub 03-90
; first version, replaces the appropriate routine from fixnum.s.
; Should be faster in more common cases. Division is done by 68000 divu
; operations if divisor is only 16 bits wide. Otherwise the normal division
; algorithm as described in various papers takes place. The division routine
; delivers the quotient in d0 and the remainder in d1, thus the implementation
; of the modulo operation is trivial. We gain some extra speed by inlining
; the division code here instead of calling __udivsi3.
text
even
xdef __CXD22
__CXD22:
movem.l d0-d3,-(sp)
subq.w #4,sp
clr.w -(sp) ; sign flag
clr.l d0 ; prepare result
move.l 10(sp),d2 ; get divisor
beq.s 10$ ; divisor = 0 causes a division trap
bpl.s 1$ ; divisor < 0 ?
neg.l d2 ; negate it
not.w (sp) ; remember sign
1$: move.l 6(sp),d1 ; get dividend
bpl.s 2$ ; dividend < 0 ?
neg.l d1 ; negate it
not.w (sp) ; remember sign
2$:
;== case 1) divident < divisor
cmp.l d2,d1 ; is divident smaller then divisor ?
bcs.s 7$ ; yes, return immediately
;== case 2) divisor has <= 16 significant bits
tst.w 10(sp)
bne.s 4$ ; divisor has only 16 bits
move.w d1,d3 ; save dividend
clr.w d1 ; divide dvd.h by dvs
swap d1
beq.s 3$ ; (no division necessary if dividend zero)
divu.w d2,d1
3$: move.w d1,d0 ; save quotient.h
swap d0
move.w d3,d1 ; (d0.h = remainder of prev divu)
divu.w d2,d1 ; divide dvd.l by dvs
move.w d1,d0 ; save quotient.l
clr.w d1 ; get remainder
swap d1
bra.s 7$ ; and return
;== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
4$:
moveq.l #31,d3 ; loop count
5$:
add.l d1,d1 ; shift divident ...
addx.l d0,d0 ; ... into d0
cmp.l d2,d0 ; compare with divisor
bcs.s 6$
sub.l d2,d0 ; big enough, subtract
add.w #1,d1 ; and note bit into result
6$:
dbra d3,5$
exg d0,d1 ; put quotient and remainder in their registers
7$:
tst.w 6(sp) ; must the remainder be corrected ?
bpl.s 8$
neg.l d1 ; yes, apply sign
; the following line would be correct if modulus is defined as in algebra
; add.l 6(sp),d1 ; algebraic correction: modulus can only be >= 0
8$: tst.w (sp)+ ; result should be negative ?
bpl.s 9$
neg.l d0 ; yes, negate it
9$:
lea 12(sp),sp
movem.l (sp)+,d2-d3
rts
10$:
divu d2,d1 ; cause division trap
bra 7$ ; back to user
end